﻿using FinalYear.Helpers;
using System.Collections.Generic;
using System.Linq;

namespace FinalYear.OpticalFlow.Classes
{
    /// <summary>
    /// Class that would map the distance from each of the tracked points
    /// </summary>
    public class OpticalFlowStore
    {
        /// <summary>
        /// Gets or sets the mean flow.
        /// </summary>
        /// <value>
        /// The mean flow.
        /// </value>
        public double meanFlow { get; set; }

        /// <summary>
        /// Gets or sets the sum flow.
        /// </summary>
        /// <value>
        /// The sum flow.
        /// </value>
        public double sumFlow { get; set; }

        /// <summary>
        /// Gets or sets the flow count.
        /// </summary>
        /// <value>
        /// The flow count.
        /// </value>
        public double flowCount { get; set; }

        /// <summary>
        /// Gets the left.
        /// </summary>
        /// <value>
        /// The left.
        /// </value>
        public GroundCount left { get; private set; }

        /// <summary>
        /// Gets the right.
        /// </summary>
        /// <value>
        /// The right.
        /// </value>
        public GroundCount right { get; private set; }

        /// <summary>
        /// Gets or sets the sky count.
        /// </summary>
        /// <value>
        /// The sky count.
        /// </value>
        public int skyCount { get; set; }

        /// <summary>
        /// Gets or sets the collision count.
        /// </summary>
        /// <value>
        /// The collision count.
        /// </value>
        public int collisionCount { get; set; }

        /// <summary>
        /// Gets or sets the collision time.
        /// </summary>
        /// <value>
        /// The collision time.
        /// </value>
        public float collisionTime { get; set; }

        /// <summary>
        /// Gets or sets the total collision time.
        /// </summary>
        /// <value>
        /// The total collision time.
        /// </value>
        public float totalCollisionTime { get; set; }

        /// <summary>
        /// Gets or sets the left ground coordinates.
        /// </summary>
        /// <value>
        /// The left ground coordinates.
        /// </value>
        public List<GroundCoordinate> leftGroundCoordinates { get; set; }

        /// <summary>
        /// Gets or sets the right ground coordinates.
        /// </summary>
        /// <value>
        /// The right ground coordinates.
        /// </value>
        public List<GroundCoordinate> rightGroundCoordinates { get; set; }

        /// <summary>
        /// Gets or sets the current center distances.
        /// </summary>
        /// <value>
        /// The current center distances.
        /// </value>
        public PointFlowMagnitudes currentCenterDistances { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="OpticalFlowStore" /> class.
        /// </summary>
        /// <param name="maxHypotenuse">The max hypotenuse.</param>
        public OpticalFlowStore(int maxHypotenuse)
        {
            this.leftGroundCoordinates = new List<GroundCoordinate>();
            this.rightGroundCoordinates = new List<GroundCoordinate>();
            this.left = new GroundCount();
            this.right = new GroundCount();
            this.currentCenterDistances = new PointFlowMagnitudes(maxHypotenuse);
        }

        /// <summary>
        /// Computes the ground count.
        /// </summary>
        public void ComputeGroundCount()
        {
            this.left.groundCount = this.leftGroundCoordinates.Count();
            this.left.region = SCREENREGION.LEFT;
            this.left.sumGroundCountX = this.leftGroundCoordinates.Sum(ground => (int)(ground.originalPoint.X - ground.translatedPoint.X));
            this.left.sumGroundCountY = this.leftGroundCoordinates.Sum(ground => (int)(ground.originalPoint.Y - ground.translatedPoint.Y));
            this.left.flow = (this.left.groundCount > 0) ? this.left.sumGroundCountX / this.left.groundCount : 0;

            this.right.groundCount = this.rightGroundCoordinates.Count();
            this.right.region = Helpers.SCREENREGION.RIGHT;
            this.right.sumGroundCountX = this.rightGroundCoordinates.Sum(ground => (int)(ground.originalPoint.X - ground.translatedPoint.X));
            this.right.sumGroundCountY = this.rightGroundCoordinates.Sum(ground => (int)(ground.originalPoint.Y - ground.translatedPoint.Y));
            this.right.flow = (this.right.groundCount > 0) ? this.right.sumGroundCountX / this.right.groundCount : 0;
        }
    }
}